package top.mcwebsite.markdown

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import org.intellij.markdown.IElementType
import org.intellij.markdown.MarkdownElementTypes
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
import org.intellij.markdown.parser.MarkdownParser
import top.mcwebsite.markdown.model.MarkdownNode
import top.mcwebsite.markdown.render.MarkdownComponent
import top.mcwebsite.markdown.render.defaultRenderMap
import top.mcwebsite.markdown.theme.LocalMarkdownTheme


@Composable
fun Markdown(
    content: String,
    state: MarkdownState = remember { buildMarkdownState() },
    renders: Map<IElementType, MarkdownComponent> = defaultRenderMap,
    flavor: MarkdownFlavourDescriptor = GFMFlavourDescriptor(),
    modifier: Modifier = Modifier,
) {
    val parsedTree = remember(content) {
        val parsedTree = MarkdownParser(flavor).buildMarkdownTreeFromString(content)
        parsedTree.children.filter { it.type == MarkdownElementTypes.LINK_DEFINITION }
            .forEach { state.addLinkDefinition(it, content) }
        parsedTree
    }
    val scrollState = rememberScrollState()
    state.scrollState = scrollState
    val theme = LocalMarkdownTheme.current
    LaunchedEffect(state.event.value) {
        when (val event = state.event.value) {
            is MarkdownInternEvent.OnClickAnchor -> {
                state.scrollToHeader(event.header)
            }
            null -> {
                println("null")
            }
        }
    }
    Column(
        modifier = modifier
            .padding(theme.contentPadding)
            .verticalScroll(scrollState)
    ) {
        parsedTree.children.forEach {
            renders[it.type]?.render(MarkdownNode(it, content, state, renders))
                ?: throw IllegalArgumentException("Unknown type: ${it.type}")
        }
    }
}